<template>
  <div :id="tableId" style="position: relative;" @contextmenu.prevent.stop>
    <right-key-menu :ref="tableId+'menu'" :menu-list="menuList" />
    <!-- <set-type-tip :ref="tableId+'setTypeTip'" :table-id="tableId" :table-model="tableModel" /> -->
    <div
      class="dynamic-table-wapper"
      :style="{
        borderTop: `1px solid ${options.rowBorderColor ? options.rowBorderColor : '#dfe6ec'}`,
        borderBottom: `1px solid ${options.rowBorderColor ? options.rowBorderColor : '#dfe6ec'}`,
        borderLeft: `1px solid ${options.colBorderColor ? options.colBorderColor : '#dfe6ec'}`,
        borderRight: `1px solid ${options.colBorderColor ? options.colBorderColor : '#dfe6ec'}`,}"
    >
      <table
        v-if="reflush"
        :key="renderTHeadData.length+renderTBodyData.length"
        class="dynamic-table"
        :class="{'isPreview':!isEdit,'noPreview':isEdit}"
        @mousedown.stop="mouseDown"
        @mousemove.stop="mouseMove"
        @mouseup.stop="mouseUp"
        @mouseleave.stop="endSelect"
      >
        <colgroup v-for="item in cols" :key="item" :style="{width: 1/cols*100 +'%'}" />
        <!-- 表头部分  -->
        <tr v-for="(tr, row) in renderTHeadData" :key="'throw'+row">
          <template v-for="(th, col) in tr">
            <th
              v-if="!th.isRemove && (isShow ? th.isShow : true)"
              :key="`th-${row}-${col}}`"
              style="background-color: #F9FAFB;"
              :rowspan="th.rowspan || 1"
              :colspan="th.colspan || 1"
              :align="alignDict[th.align]"
              :valign="valignDict[th.valign]"
              :data-select-flag="`th-${row}-${col}-${th.rowspan}-${th.colspan}`"
              :style="{
                height:calculationHeight(th),
                width:calculationWidth(th),
                borderTop: `1px solid ${options.rowBorderColor ? options.rowBorderColor : '#dfe6ec'}`,
                borderBottom: `1px solid ${options.rowBorderColor ? options.rowBorderColor : '#dfe6ec'}`,
                borderLeft: `1px solid ${options.colBorderColor ? options.colBorderColor : '#dfe6ec'}`,
                borderRight: `1px solid ${options.colBorderColor ? options.colBorderColor : '#dfe6ec'}`,
                color: th.isColorChange ? th.color : '#000000',
                backgroundColor: th.cellFill,
                fontSize: sizeDict[th.size],
                fontStyle:th.isItalic ? 'italic' : 'normal',
                textDecoration:th.underline ? 'underline' : 'none',
                fontWeight: th.isWeight ? 'bold' : 'normal' }"
              :class="{'cell':true,'brder-right-none':col+th.colspan>=tr.length,'brder-bottom-none':renderTBodyData.length==0&&row+th.rowspan>=renderTHeadData.length,
                       'isedit':th.isEditCell&&th.cellType==='text'&&!selectCells.includes(`th-${row}-${col}-${th.rowspan}-${th.colspan}`),
                       select:selectCells.includes(`th-${row}-${col}-${th.rowspan}-${th.colspan}`)
              }"
              @click="tablePropertiesInputValue(th)"
              @drop.stop="handleTargetDrop"
              @dragover="handleTargetDragOver"
            >
              <!-- 一种是回显 -->
              <span v-show="row === renderTHeadData.length - 1 || !isEdit">
                {{ getVal('th', th, row,col) }}
              </span>
              <!-- 一种是可输入 -->
              <evol-input
                v-if="!(row === renderTHeadData.length - 1 || !isEdit)"
                :ref="`th-${row}-${col}-${th.rowspan}-${th.colspan}val`"
                v-model="th.val"
                :is-edit="isEdit"
              />
            </th>
          </template>

        </tr>
        <tr v-if="options.dataType=='dynamic'">
          <td :colspan="cols" align="center" style="padding:50px 0;">接口动态数据数据</td>
        </tr>
        <!-- 表格主体 		 -->
        <tr v-for="(tr,row) in renderTBodyData" :key="'tdrow'+row">
          <template v-for="(td,col) in tr">
            <!-- color: td.color,-->
            <!-- td被删除不显示   传入是否显示标记为true时,根据单元格属性判断是否显示  通过预览界面进入默认不显示-->
            <td
              v-if="!td.isRemove && (isShow ? td.isShow : true) && showTableTd"
              :key="`td-${row}-${col}`"
              :rowspan="td.rowspan || 1"
              :colspan="td.colspan || 1"
              :align="alignDict[td.align]"
              :valign="valignDict[td.valign]"
              style="color: #8691A0;"
              :style="{ height:calculationHeight(td),
                        width:calculationWidth(td),
                        borderTop: `1px solid ${options.rowBorderColor ? options.rowBorderColor : '#dfe6ec'}`,
                        borderBottom: `1px solid ${options.rowBorderColor ? options.rowBorderColor : '#dfe6ec'}`,
                        borderLeft: `1px solid ${options.colBorderColor ? options.colBorderColor : '#dfe6ec'}`,
                        borderRight: `1px solid ${options.colBorderColor ? options.colBorderColor : '#dfe6ec'}`,
                        backgroundColor: td.cellFill,
                        color: td.isColorChange ? td.color : (isEdit ? '#8691A0' : '#000000'),
                        fontSize: sizeDict[td.size],
                        fontStyle:td.isItalic ? 'italic' : 'normal',
                        textDecoration:td.underline ? 'underline' : 'none',
                        fontWeight: td.isWeight ? 'bold' : 'normal' }"
              :data-select-flag="`td-${row}-${col}-${td.rowspan}-${td.colspan}`"
              :class="{'cell':true,'brder-bottom-none':row+td.rowspan>=renderTBodyData.length,
                       'isedit':td.isEditCell&&td.cellType==='text'&& !selectCells.includes(`td-${row}-${col}-${td.rowspan}-${td.colspan}`),
                       select:selectCells.includes(`td-${row}-${col}-${td.rowspan}-${td.colspan}`)
              }"
              @click="tablePropertiesInputValue(td)"
            >
              <span>
                {{ getVal('td',td,row,col) }}
              </span>
            </td>
          </template>
        </tr>
      </table>
      <div
        v-if="isShowNoData"
        class="d-flex j-center"
        :style="{
          borderTop: `1px solid ${options.rowBorderColor ? options.rowBorderColor : '#dfe6ec'}`}"
      >
        <v-noData />
      </div>
    </div>
  </div>
</template>

<script>
// 一个单元格的属性
const defaultCell = {
  val: '',
  rowspan: 1,
  colspan: 1,
  key: '',
  cellType: 'text', // text radio checkbox result
  label: '',
  otherVal: '', // 如果不是text，那选择radio之类的就是改变这个值
  otherSelect: '', // 同上
  isRemove: false,
  isEditCell: false, // 用户是否可以编辑 text单元默认可编辑 在setTable中设置
  size: '中',
  isColorChange: false,
  color: '#8691A0',
  isWeight: false,
  isItalic: false,
  underline: false,
  align: '中',
  valign: '中'
}
// 获取单元格
function getCell(dom) {
  if (dom.tagName === 'BODY') return null
  return (dom.tagName === 'TH' || dom.tagName === 'TD') ? dom : getCell(dom.parentNode)
}
// 数组求和
function sum(arr) {
// eslint-disable-next-line no-eval
  return eval(arr.join('+'))
}
// 右键菜单组件
import RightKeyMenu from '../right-key-menu.vue'
import EvolInput from '../evol-input.vue'
let uid = 0
/**
 * 动态表格
 */
export default {
  components: {
    RightKeyMenu,
    EvolInput
  },
  props: {
    value: {
      type: Object,
      default: () => {}
    },
    action: {
      type: Number,
      default: 1 // 0 创建新表格 1 使用数据 构建更新表格 2修改api
    },
    align: {
      type: String,
      default: 'center'
    },
    valign: {
      type: String,
      default: 'middle'
    },
    loadOptions: {
      type: Boolean,
      default: true
    },
    tableTitle: {
      type: String,
      default: ''
    },
    // 是否为编辑
    isEdit: {
      type: Boolean,
      default: true
    },
    // 表格数据 用于静态渲染
    tableData: {
      type: Object,
      default: () => {}
    },
    tableModel: {
      type: Number,
      default: 0
    }, // 快捷设置  文本、单选、复选
    // 表格配置
    options: {
      type: Object,
      default: () => {
        return {
        // 数据类型
          dataType: 'static', // dynamic 动态数据 static 静态数据
          bandApi: '', // 绑定接口  只在 动态数据时有效
          inParams: [], // 绑定接口入参
          headRowNum: 0, // 表头行数
          bodyRowNum: 0, // body行数
          colNum: 0, // 列数
          thData: [], //
          tdData: []
        }
      }
    },
    cellOptions: {
      type: Object,
      default: () => {}
    },
    // 每一个单元格中的isShow是否生效
    isShow: {
      type: Boolean,
      default: false
    },
    // 当前拖拽的数据
    dataTransferData: {
      type: Object,
      default: () => {}
    }
  },
  data() {
    return {
      dataComplete: false, // 数据加载完成标志
      sizeDict: {
        '小': '11px',
        '中': '13px',
        '大': '15px'
      },
      alignDict: {
        '左': 'left',
        '中': 'center',
        '右': 'right'
      },
      valignDict: {
        '上': 'top',
        '中': 'middle',
        '下': 'bottom'
      },
      tableJson: '', // 表格json缓存
      reflush: true, // 强制刷新表格
      // 对齐方式
      result: 0,
      cellHeight: 30, // 一个单元格的基础高度
      cellWidth: 25,
      tableId: 'evol-' + +new Date(),
      renderTHeadData: [],
      renderTBodyData: [],
      renderTBodyDataCopy: [],		// 用于设置值
      selectCells: [], // 被选中的单元格 标志数组
      cells: null,
      mouseEventDom: null, // 鼠标当前所在单元格
      timer: null, // 选择定时器 单鼠标按下并且移动时 开始框选
      mouseDownCell: null, // 鼠标按下时的节点
      rightDownCell: null, // 鼠标右键按下的节点
      menuList: [], // 右键菜单列表
      allowMerging: false, // 是否允许合并单元格
      currDataType: 'static',
      defaultVal: [],
      isShowNoData: false
    }
  },
  computed: {
    // 单元格是否显示额外规则
    showTableTd() {
      // 当前不是编辑模式
      if (!this.isEdit) {
        // 数据加载完成则显示 否则不显示
        return this.dataComplete
      } else {
        // 否则默认为显示
        return true
      }
    },
    currBandApi() {
      return this.options.bandApi
    },
    isShowSelect() {
      return this.options.dataType === 'dynamic'
    },
    cols() {
      if (this.renderTHeadData.length === 0 && this.renderTBodyData.length === 0) {
        return 0
      } else if (this.renderTHeadData.length === 0) {
        return this.renderTBodyData[0].length
      }
      return this.renderTHeadData[0].length
    }
  },
  watch: {
    isShowSelect() { // 动静态数据发生改变 清除th显示信息
      this.renderTHeadData.forEach(item => {
        item.forEach(cell => {
          cell.val = ''
        })
      })
    },
    options: {
      handler(val) {
        if (this.options.changeKey && this.options.changeKey.length) {
          this.setTableStyle()
        }
      },
      immediate: true, // 刷新加载 立马触发一次handler
      deep: true // 可以深度检测到  对象的属性值的变化
    },
    tableModel(val) {
    // this.$emit("update:isEdit",false)
      this.renderTBodyData.forEach(row => {
        row.forEach((currCell, index) => {
        // const cell = { ... defaultCell }
          const types = ['text', 'radio', 'checkbox']
          currCell.label = ''
          currCell.otherVal = ''
          currCell.val = ''
          currCell.otherSelect = ''
          currCell.cellType = types[val]
          currCell.otherSelect = false
        })
      })
    },
    isEdit(val) {
      if (!val) {
        // this.$refs[this.tableId + 'setTypeTip'].close()
        this.selectCells = []
      }
    },
    cellOptions: {
      handler(val) {
        if (this.cellOptions.changeKey && this.cellOptions.changeKey.length) {
          this.setSelectCellStyle()
        }
      },
      deep: true // 可以深度检测到  对象的属性值的变化
    }
  },
  methods: {
    /**
     * 计算表格属性高度的改变值
     * @param {Object} td
     */
    calculationHeight(td) {
      // return td.tableCellHeight&&td.tableCellHeight<=2000&&td.tableCellHeight>=30?td.tableCellHeight*td.rowspan+'px':this.cellHeight+'px'
      return td.tableCellHeight ? td.tableCellHeight * td.rowspan + 'px' : '30px'
    },
    /**
     * 计算表格属性宽度的改变值
     * @param {Object} td
     */
    calculationWidth(td) {
      // return td.tableCellWidth&&td.tableCellWidth<=100&&td.tableCellWidth>0?td.tableCellWidth*td.rowspan+'%':this.cellWidth+'%'
      return td.tableCellWidth * td.rowspan + '%'
    },
    /**
     * 选择某个单元格后再回显表格属性的宽度和高度
     */
    tablePropertiesInputValue(val) {
      if (!this.isEdit) return
      const height = isNaN(parseInt(this.calculationHeight(val))) ? this.cellHeight : parseInt(this.calculationHeight(val))
      const width = isNaN(parseInt(this.calculationWidth(val))) ? this.cellWidth : parseInt(this.calculationWidth(val))

      this.$parent.sendEasyTable([width, height])
      // this.$EventBus.$emit('inputValue',[parseInt(this.calculationWidth(val)),parseInt(this.calculationHeight(val))])
    },
    /**
		 * 取消事件的默认动作
		 * @param {Object} e
		 */
    handleTargetDragOver(e) {
      // 合计项禁止拖拽
      if (['transverseTotal', 'verticalTotal'].includes(this.dataTransferData.key)) return false
      const cell = getCell(e.toElement || e.explicitOriginalTarget)
      // 得到当前选中单元格的样式配置
      const cellInfoParse = this.cellInfoParse(cell.dataset.selectFlag)
      if (cellInfoParse.rowIndex + 1 === this.renderTHeadData.length) e.preventDefault()
    },
    /**
		 * 拖拽放置(只允许拖到固定的那一列表头)
		 * @param {Object} e
		 */
    handleTargetDrop(e) {
      // return false
      const cell = getCell(e.toElement || e.explicitOriginalTarget)
      // 得到当前选中单元格的样式配置
      const cellInfoParse = this.cellInfoParse(cell.dataset.selectFlag)
      if (cellInfoParse.rowIndex + 1 !== this.renderTHeadData.length) return false

      const content = JSON.parse(e.dataTransfer.getData('dragData'))
      // 遍历最后一行tr的th找到拖到了哪一个格子
      // eslint-disable-next-line no-undef
      for (let i = 0; i < $(`.dynamic-table tr:eq(${this.renderTHeadData.length - 1}) th`).length; i++) {
        // eslint-disable-next-line no-undef
        const thObject = $(`.dynamic-table tr:eq(${this.renderTHeadData.length - 1}) th`).eq(i)
        const left = thObject.offset().left
        const outerWidth = thObject.outerWidth()
        if (left + outerWidth >= e.screenX) {
          // 数据填充(表头最后一行)
          const renderThData = this.renderTHeadData[this.renderTHeadData.length - 1][i]
          renderThData['val'] = content.label
          renderThData['dataSetCode'] = content.dataSetCode
          renderThData['dataSetName'] = content.dataSetName
          renderThData['supportTotal'] = content.supportTotal
          renderThData['key'] = content.key
          renderThData['label'] = content.label
          renderThData['resultType'] = content.resultType
          // 表体的赋值
          this.renderTBodyData.forEach(item => {
            for (let j = 0; j < item.length; j++) {
              if (j === i) {
                item[i].val = `值(${content.label})`
                break
              }
            }
          })
          return
        }
      }
      e.preventDefault()
      // 通常不需要阻止冒泡，但是当出现容器嵌套时最好这么做
      // 它可以防止节点被添加到数组中两次
      e.stopPropagation()
    },
    /**
		 * 向外提供个获取当前拖拽的列数据方法
		 */
    getDataSetMappingRefList() {
      const result = []
      this.renderTHeadData[0].forEach(item => {
        if (item.dataSetCode && item.key)	result.push(item.dataSetCode + '&' + item.key)
      })
      return [...new Set(result)]
    },
    /**
		 * 向外提供个保存表格json的方法
		 */
    getTableJSON() {
      return JSON.stringify({
        data: {
          thData: this.renderTHeadData,
          tdData: this.renderTBodyData
        },
        options: this.options
      })
    },
    /**
		 * 设置选中单元格的样式
		 */
    setSelectCellStyle() {
      this.selectCells.forEach(item => {
        const cellInfoParse = this.cellInfoParse(item)
        this.cellOptions.changeKey.forEach(item2 => {
          if (cellInfoParse.tag === 'td') {
            this.renderTBodyData[cellInfoParse.rowIndex][cellInfoParse.colIndex][item2] = this.cellOptions[item2]
            // this.cellHeight = this.renderTBodyData[cellInfoParse.rowIndex][cellInfoParse.colIndex].tableCellHeight?this.renderTBodyData[cellInfoParse.rowIndex][cellInfoParse.colIndex].tableCellHeight:this.cellHeight
          }
          else {
            this.renderTHeadData[cellInfoParse.rowIndex][cellInfoParse.colIndex][item2] = this.cellOptions[item2]
          }
          this.$forceUpdate()
        })
      })
    },
    /**
		 * 设置表格整体的颜色
		 */
    setTableStyle() {
      const setColor = (arr, color) => {
        arr.forEach(item => {
          item.forEach(item2 => {
            item2.cellFill = color
          })
        })
        return arr
      }
      // 设置表头或者表体的颜色
      this.options.changeKey.forEach(item => {
        if (item === 'headerFill') {
          this.renderTHeadData = setColor(this.renderTHeadData, this.options.headerFill)
        }
        else if (item === 'cellFill') {
          this.renderTBodyData = setColor(this.renderTBodyData, this.options.cellFill)
        }
        // else{
        // 	// 单个属性设置值
        // 	this.options[]
        // }
      })
    },
    /**
		 * 表格回显
		 * @param {Object} tableJson
		 */
    echoTable(tableJson) {
      // 默认设置数据未加载
      this.dataComplete = false
      // 转换js对象
      tableJson = JSON.parse(tableJson)
      // 缓存js对象
      this.tableJson = tableJson
      // 设置表头对象
      this.renderTHeadData = tableJson.data.thData || []
      // 设置表体对象
      this.renderTBodyData = tableJson.data.tdData || []
      this.$forceUpdate()
    },
    /**
     * 表格设置值
     * @param {Object} table					多条数据集
     * @param {Object} singleDataMap  单条数据集
     */
    tableSetValue(table, singleDataMap) {
      // 默认设置数据未加载
      this.dataComplete = false
      // 同步缓存数据  如果缓存没有值 则将当前数据赋值给缓存 如果缓存有值 则将缓存数据赋值给当前数据
      !this.renderTBodyDataCopy.length ? (this.renderTBodyDataCopy = JSON.parse(JSON.stringify(this.renderTBodyData))) : (this.renderTBodyData = JSON.parse(JSON.stringify(this.renderTBodyDataCopy)))
      // renderTBodyData与传进来的table保持一致
      if (table.length < this.renderTBodyData.length) {
        // 删减
        this.renderTBodyData.length = table.length
        this.$forceUpdate()
      } else {
        // 获取当前表格数据长度
        const bodyLength = this.renderTBodyData.length
        // 追加
        for (let i = 0; i < table.length - bodyLength; i++) {
          // 超过当前长度的数据，按照最后一行表体数据赋值
          this.renderTBodyData.push(JSON.parse(JSON.stringify(this.renderTBodyDataCopy[this.renderTBodyDataCopy.length - 1])))
        }
        this.$forceUpdate()
      }

      /**
       * 加法运算,解决精度问题
       * @param {Object} num1
       * @param {Object} num2
       */
      const numAdd = (num1, num2) => {
        var baseNum, baseNum1, baseNum2
        try {
          baseNum1 = num1.toString().split('.')[1].length
        } catch (e) {
          baseNum1 = 0
        }
        try {
          baseNum2 = num2.toString().split('.')[1].length
        } catch (e) {
          baseNum2 = 0
        }
        baseNum = Math.pow(10, Math.max(baseNum1, baseNum2))
        return (num1 * baseNum + num2 * baseNum) / baseNum
      }

      // 开启行合计数  动态为表头、表体的每行数据 末尾增加一项合计对象
      if (this.tableJson.options.isRowTotal) {
        // 表头处理
        if (this.renderTHeadData.length) {
          this.renderTHeadData.forEach((item, index) => {
            // 获取本行的最后一列数据对象
            const lastColData = JSON.parse(JSON.stringify(item[item.length - 1]))
            // 获取到最后一行的key不为transverseTotal 时 则添加数据 防止重复添加
            if (lastColData.key !== 'transverseTotal') {
              // 设置属性
              lastColData.align = '中' // 文字水平对齐方式默认居中
              lastColData.valign = '中' // 文字垂直对齐方式默认居中
              lastColData.cellFill = this.tableJson.options.headerFill // 表头填充色取缓存配置
              lastColData.cellType = 'text' // 默认类型
              lastColData.color = '#f80c0c' // 默认红色
              lastColData.isRemove = false // 默认为不删除
              lastColData.colspan = 1 // 列合并默认为1
              lastColData.key = 'transverseTotal' // 设置key值
              lastColData.rowspan = 1 // 行合并默认设置为1
              lastColData.size = '大' // 文字尺寸默认设置为大
              lastColData.label = '行合计' // 设置label值
              if (index === this.renderTHeadData.length - 1) {
                lastColData.val = '行合计' // 文字显示
              } else {
                lastColData.val = '' // 文字显示
              }
              // 将数据添加值数组中
              item.push(lastColData)
            }
          })
        }
        // 表格处理
        if (this.renderTBodyData.length) {
          this.renderTBodyData.forEach((item, index) => {
            // 获取本行的最后一列数据对象
            const lastColData = JSON.parse(JSON.stringify(item[item.length - 1]))
            // 获取到最后一行的key不为transverseTotal 时 则添加数据 防止重复添加
            if (lastColData.key !== 'transverseTotal') {
            // 设置属性
              lastColData.align = '中' // 文字水平对齐方式默认居中
              lastColData.valign = '中' // 文字垂直对齐方式默认居中
              lastColData.cellFill = this.tableJson.options.cellFill // 单元格填充色取缓存配置
              lastColData.cellType = 'text' // 默认类型
              lastColData.isWeight = true // 默认加粗
              lastColData.isItalic = true // 默认斜体
              lastColData.underline = true // 默认下划线
              lastColData.colspan = 1 // 列合并默认为1
              lastColData.isRemove = false // 默认不删除
              lastColData.key = 'transverseTotal' // 设置key值
              lastColData.rowspan = 1 // 行合并默认设置为1
              lastColData.size = '中' // 文字尺寸默认设置为中
              lastColData.isWeight = true // 默认加粗
              lastColData.isItalic = true // 默认斜体
              lastColData.underline = true // 默认下划线
              lastColData.label = '行合计' // 设置label值
              lastColData.val = '行合计' // 文字显示
              // 将数据添加值数组中
              item.push(lastColData)
            }
          })
        }
      }

      // 开启列合计数  动态为表体的末尾增加一行数据
      if (this.tableJson.options.isColTotal) {
        // 表格处理
        if (this.renderTBodyData.length) {
          // 获取表体最后一行数据
          const lastTBodyDataArray = JSON.parse(JSON.stringify(this.renderTBodyData[this.renderTBodyData.length - 1]))
          // 判断不为空
          if (lastTBodyDataArray && lastTBodyDataArray.length) {
            // 获取到最后一行的key不为verticalTotal 时 则添加数据 防止重复添加
            if (lastTBodyDataArray[0].key !== 'verticalTotal') {
              // 遍历数据
              lastTBodyDataArray.forEach(item => {
                // 设置属性
                item.align = '中' // 文字水平对齐方式默认居中
                item.valign = '中' // 文字垂直对齐方式默认居中
                item.cellFill = this.tableJson.options.cellFill // 单元格填充色取缓存配置
                item.cellType = 'text' // 默认类型
                item.isWeight = true // 默认加粗
                item.isItalic = true // 默认斜体
                item.underline = true // 默认下划线
                item.isRemove = false // 默认不删除
                item.colspan = 1 // 列合并默认为1
                item.key = 'verticalTotal' // 设置key值
                item.rowspan = 1 // 行合并默认设置为1
                item.size = '中' // 文字尺寸默认设置为中
                item.label = '列合计' // 设置label值
                item.val = '列合计' // 文字显示
              })
              // 添加到数组中
              this.renderTBodyData.push(lastTBodyDataArray)
            }
          }
        }
      }
      // 无数据标记
      this.isShowNoData = !table.length
      // 遍历行
      table.forEach((item, index) => {
        // 遍历列
        for (const i in item) {
          // 拿到header中存储的key的索引
          const cellIndexArr = this.renderTHeadData[this.renderTHeadData.length - 1].map((item, index) => item.key === i.split('&')[1] && index).filter(item => item !== false)
          // console.log(cellIndexArr + '<===>' + item[key])
          // 设置值
          cellIndexArr.forEach((item2, index2) => {
            this.renderTBodyData[index][item2].val = item[i]
          })
          this.$forceUpdate()
        }
      })
      // 计算数据
      this.renderTBodyData.forEach((item2, index) => {
        for (let i = 0; i < item2.length; i++) {
          const item = item2[i]
          // 自主输入的+对空单元格  不进行处理
          if (!item['val']) continue
          // 获取表头数据
          const theadData = this.renderTHeadData[this.renderTHeadData.length - 1]
          // 设置横向合计
          if (item.key === 'transverseTotal') {
            // 当前行当前位置向前追溯
            let transverseTotal = 0
            for (let j = 0; j < item2.length; j++) {
              // 仅循环当前下标之前的数据
              if (j === i) break
              // 获取表头部分的合计标志
              const supportTotal = (theadData && theadData.length && theadData[j].supportTotal) ? theadData[j].supportTotal : false
              // 当前为数字且不为空 调用方法累加数据
              if (!isNaN(item2[j].val) && item2[j].val !== '' && supportTotal) transverseTotal = numAdd(parseFloat(item2[j].val), transverseTotal)
            }
            item['val'] = transverseTotal
          }
          // 设置纵向合计
          if (item.key === 'verticalTotal') {
            // 当前列当前位置向上追溯
            let verticalTotal = 0
            for (let j = 0; j < this.renderTBodyData.length; j++) {
              // 仅循环当前下标之前的数据
              if (j === index) break
              const val = this.renderTBodyData[j][i].val
              // 获取表头部分的合计标志
              let supportTotal = (theadData && theadData.length && theadData[i].supportTotal) ? theadData[i].supportTotal : false
              // 如果开启了行合计 且当前为最后一项  则说明最后一项为 行合计的列合计
              if (this.tableJson.options.isRowTotal && i === item2.length - 1) {
                // 需要默认开启合计处理
                supportTotal = true
              }
              // 当前为数字且不为空 调用方法累加数据
              if (!isNaN(val) && val !== '' && supportTotal) {
                verticalTotal = numAdd(parseFloat(val), verticalTotal)
              }
            }
            item['val'] = verticalTotal
          }
        }
      })

      // 设置数据加载完成
      this.dataComplete = true
      // 创建返回对象
      const returnData = {
        renderTHeadData: JSON.parse(JSON.stringify(this.renderTHeadData)),
        renderTBodyData: JSON.parse(JSON.stringify(this.renderTBodyData))
      }
      // 返回对象
      return returnData
    },
    /**
		 * 清空选中的单元格
		 */
    clearSelect() {
      this.selectCells = []
    },
    /**
		 * 行列发生变化的时候触发
		 */
    rowCelChange() {
      this.$nextTick(() => {
        const data = JSON.parse(JSON.stringify(this.options))
        data.bodyRowNum = this.renderTBodyData.length
        data.colNum = this.renderTBodyData[0].length
        this.$emit('changeTableSeting', {
          type: 'table',
          data: data
        })
      })
    },
    getUid() {
      return uid++
    },
    watchUpdateAction(val) {
      this.$nextTick(() => {
        if (this.action === 0) {
          this.setTable(val.headRowNum, val.bodyRowNum, val.colNum)
        } else if (this.action === 1) {
          // 数据渲染
          this.updateOrCreateTable(val)
        }
      })
    },
    updateOrCreateTable(val) {
      if (val.thData.length !== 0 || val.tdData.length !== 0) {
        this.renderTHeadData = val.thData.slice(0)
        this.renderTBodyData = val.tdData.slice(0)
        this.$nextTick(() => {
          this.selectCells = []
        })
      } else {
        this.setTable(val.headRowNum, val.bodyRowNum, val.colNum)
      }
    },
    createTable(opt) {
      const newOptions = {}
      Object.assign(newOptions, this.options)
      newOptions.headRowNum = parseInt(opt.headRowNum)
      newOptions.bodyRowNum = parseInt(opt.bodyRowNum)
      newOptions.colNum = parseInt(opt.colNum)
      // this.tableModel = opt.tableModel||0
      this.setTable(newOptions.headRowNum, newOptions.bodyRowNum, newOptions.colNum)
    // this.$emit('update:options', newOptions)
    },
    /**
		 * 设置表格
		 * @param {Object} headRowNum
		 * @param {Object} bodyRowNum
		 * @param {Object} colNum
		 */
    setTable(headRowNum, bodyRowNum, colNum) {
      this.reflush = false
      this.$nextTick(() => {
        this.reflush = true
        this.selectCells = []
        // this.$refs[this.tableId + 'setTypeTip'].close()
        const cell = { ... defaultCell }

        const types = ['text', 'radio', 'checkbox']
        cell.cellType = types[this.tableModel]

        cell.otherSelect = false
        this.renderTHeadData = new Array(headRowNum).fill('').map(item => {
          return new Array(colNum).fill('').map(item => {
            const itemCell = { ...defaultCell }
            itemCell.isShow = itemCell.isWeight = true
            // 这里是设置表头的字体样式
            // itemCell.isItalic = itemCell.underline = true
            itemCell.cellFill = this.tableOptions ? this.tableOptions.headerFill : '#F9FAFB'
            return itemCell
          })
        })
        this.renderTBodyData = new Array(bodyRowNum).fill('').map(item => {
          return new Array(colNum).fill('').map(item => {
            const itemCell = { ...cell }
            itemCell.isShow = false
            itemCell.cellFill = this.tableOptions ? this.tableOptions.cellFill : '#FFFFFF'
            return itemCell
          })
        })
      })
    },
    getTableOffset() {
      const dom = document.getElementById(this.tableId).getElementsByClassName('dynamic-table-wapper')[0]
      return {
        top: dom.offsetTop,
        left: dom.offsetLeft,
        width: dom.offsetWidth,
        height: dom.offsetHeight
      }
    },
    execInputFunc(info, selectFlag, func) {
      const data = info.tag === 'th' ? this.renderTHeadData : this.renderTBodyData
      // }
      try {
        if (data[info.rowIndex][info.colIndex].cellType === 'text' ||
            data[info.rowIndex][info.colIndex].cellType === 'result') {
          if (this.$refs[selectFlag + 'val'] && this.$refs[selectFlag + 'val'][0]) {
            this.$refs[selectFlag + 'val'][0]['input' + func]()
          }
        } else {
          if (this.$refs[selectFlag + 'label'] && this.$refs[selectFlag + 'label'][0]) {
            this.$refs[selectFlag + 'label'][0]['input' + func]()
          }
        }
      } catch (e) {
      // console.log(e)
      }
    },
    /**
     * 选中规则
     * 鼠标动作有以下几种
     * 1.鼠标左键按下
     *    选中当前的单元格
     * 2.鼠标左键按下并且拖动
     * 		选中 起始点与与松开点的单元格
     * 3.鼠标右键按下
     *  弹出自定义菜单
     * -----------------------
     * 监听  mousedown mouseover  mouseup
     * ----------------
     */
    mouseDown(event) {
      if (!this.isEdit) {
        return
      }
      const cell = getCell(event.toElement || event.explicitOriginalTarget)
      // 获取焦点
      const info = this.cellInfoParse(cell.dataset.selectFlag)
      if (event.button === 0 && cell.dataset && cell.dataset.selectFlag) { // 左键按下
      // 获取表格中 所有cell
        this.cells = Array.from(document.getElementById(this.tableId).getElementsByClassName('cell'))
        this.$refs[this.tableId + 'menu'].closeMenu()
        this.mouseDownCell = cell
        // 选中单元格
        this.selectCells = [cell.dataset.selectFlag]
        // this.$refs[this.tableId + 'setTypeTip'].close()

        setTimeout(() => {
          // input
          if (event.target.className !== 'input') {
            this.execInputFunc(info, cell.dataset.selectFlag, 'Focus')
          }
          /*
					if (info.tag === 'td') {
            const offset = this.getTableOffset()
            this.$refs[this.tableId + 'setTypeTip'].open(
              offset.left + cell.offsetLeft,
              offset.top + cell.offsetTop + cell.offsetHeight + 15,
              this.renderTBodyData[info.rowIndex][info.colIndex].cellType,
              this.renderTBodyData[info.rowIndex][info.colIndex].label,
              this.renderTBodyData[info.rowIndex][info.colIndex].otherVal,
              (type, label, val) => {
                const cell = this.renderTBodyData[info.rowIndex][info.colIndex]
                cell.otherSelect = null
                if (type === 'text') {
                  cell.val = ''
                  cell.otherVal = ''
                  cell.cellType = 'text'
                  cell.label = ''
                } else {
                  cell.label = label
                  cell.otherVal = val
                  cell.cellType = type
                }
              }
            )
          }
					*/
        }, 80)
      } else if (event.button === 2) {
        this.rightDownCell = cell
      }
      // 鼠标右键触发的mouseDown不进行往下处理
      if (event.button === 2)	return
      // 得到当前选中单元格的样式配置
      const cellInfoParse = this.cellInfoParse(cell.dataset.selectFlag)
      let item = {}
      if (cellInfoParse.tag === 'td') {
        item = this.renderTBodyData[cellInfoParse.rowIndex][cellInfoParse.colIndex]
      }
      else {
        item = this.renderTHeadData[cellInfoParse.rowIndex][cellInfoParse.colIndex]
      }
      // 头部数据最后一行
      const lastRenderTHeadDataIndex = (this.renderTHeadData && this.renderTHeadData.length > 0) ? this.renderTHeadData.length - 1 : 0
      const cellData = {
        id: cell.dataset.selectFlag,
        size: item.size,
        color: item.isColorChange ? item.color : (cellInfoParse.tag === 'td' ? '#8691A0' : '#000000'),
        align: item.align,
        valign: item.valign,
        isWeight: item.isWeight,
        isItalic: item.isItalic,
        underline: item.underline,
        isColorChange: item.isColorChange,
        isShow: item.isShow,
        cellFill: item.cellFill,
        content: {
          dataSetCode: item.val ? this.renderTHeadData[lastRenderTHeadDataIndex][cellInfoParse.colIndex]['dataSetCode'] : '',					//
          dataSetName: item.val ? this.renderTHeadData[lastRenderTHeadDataIndex][cellInfoParse.colIndex]['dataSetName'] : '', 					//
          key: item.val ? this.renderTHeadData[lastRenderTHeadDataIndex][cellInfoParse.colIndex]['key'] : '',									// 字段编码
          label: item.val ? this.renderTHeadData[lastRenderTHeadDataIndex][cellInfoParse.colIndex]['label'] : '',								// 字段名称
          resultType: item.val ? this.renderTHeadData[lastRenderTHeadDataIndex][cellInfoParse.colIndex]['resultType'] : ''						// 返回类型
        },
        changeKey: []
      }
      // 非数据集字段拖选表头 回显内容属性处理
      if (info.tag === 'th' && info.rowIndex !== lastRenderTHeadDataIndex) {
        cellData.content = {
          dataSetCode: '',
          dataSetName: '',
          key: '',
          label: '',
          resultType: ''
        }
      }
      this.$emit('changeTableSeting', {
        type: 'cell',
        data: cellData
      })
    },
    endSelect(e) { // 结束框选
      if (!this.isEdit) {
        return
      }
      this.mouseDownCell = null
      setTimeout(() => {
        clearInterval(this.timer)
        this.timer = null
      }, 80)
    },
    mouseUp(event) {
      if (!this.isEdit) {
        return
      }
      this.endSelect()
      if (event.button === 2) {
      // 有点击目标则可打开菜单
        if (this.getCurrSingleCell()) {
          this.getMenu(event)
        }
      }
    },
    mouseMove(event) {
      if (!this.mouseDownCell) { // 没有在表格中 按下鼠标
        return
      }
      // 获取当前 鼠标在表格中的位置
      this.mouseEventDom = event.toElement
      if (!this.timer) { // 已经开启定时器 无需重复开启 没开时才会开启
        // this.$refs[this.tableId + 'setTypeTip'].close()
        this.timer = setInterval(this.selectCelling, 60)
      }
    },
    selectCelling() {
      if (!this.mouseDownCell || !this.mouseDownCell.dataset) { // 鼠标已经松开或者 已经移出表格
        return
      }
      const cells = []
      // 获取起始、结束 cell信息
      const currCell = getCell(this.mouseEventDom)
      const info1 = this.cellInfoParse(this.mouseDownCell.dataset.selectFlag)
      const info2 = this.cellInfoParse(currCell.dataset.selectFlag)
      const startCol = Math.min(info1.colIndex, info2.colIndex)
      const endCol = Math.max(info1.colIndex, info2.colIndex)
      info1.rowIndex += (info1.tag === 'td' ? this.renderTHeadData.length : 0)
      info2.rowIndex += (info2.tag === 'td' ? this.renderTHeadData.length : 0)
      const startRow = Math.min(info1.rowIndex, info2.rowIndex)
      const endRow = Math.max(info1.rowIndex, info2.rowIndex)
      const data = this.renderTHeadData.concat(this.renderTBodyData)
      // 筛选选中cell
      for (let i = 0; i <= endRow; i++) {
        for (let j = 0; j <= endCol; j++) {
          if ((i >= startRow || (data[i][j].rowspan !== 1 && i + data[i][j].rowspan > startRow)) &&
          (j >= startCol ||	(data[i][j].colspan !== 1 && j + data[i][j].colspan > startCol)) &&
                        !data[i][j].isRemove) {
            cells.push(data[i][j].selectFlag)
          }
        }
      }
      this.selectCells = cells
      if (this.selectCells.length > 1) {
        this.execInputFunc(this.cellInfoParse(this.selectCells[0]), this.selectCells[0], 'Blur')
        this.execInputFunc(this.cellInfoParse(this.selectCells[this.selectCells.length - 1]), this.selectCells[this.selectCells.length - 1], 'Blur')
        // this.$refs[this.tableId + 'setTypeTip'].close()
      }
    },
    getVal(tag, item, row, col) {
      // try{
      item.selectFlag = `${tag}-${row}-${col}-${item.rowspan || 1}-${item.colspan || 1}`
      return item.val
      // }catch(e){
      // 	//TODO handle the exception
      // 	return ''
      // }
    },
    /**
     * return  是否可进行合并单元格操作
     */
    isAllowMerge() { //
    // 1.选中的单元格 数量小于两个 不可进行合并操作
      if (this.selectCells.length < 2) {
        return false
      }
      // 2.thead不能与 tbody 合并
      const tag = this.selectCells[0].split('-')[0]
      if (this.selectCells.some(item => item.split('-')[0] !== tag)) {
        return false
      }
      // console.log(this.selectCells)
      let arr = []
      this.selectCells.forEach(item => { // 将得到的数据 解析为二维数据
        const info = this.cellInfoParse(item)
        for (let i = info.rowIndex; i < info.rowIndex + info.rowNum; i++) {
          for (let j = info.colIndex; j < info.colIndex + info.colNum; j++) {
            if (!arr[i]) { 	arr[i] = [] }
            arr[i][j] = 1
          }
        }
      })
      arr = arr.filter(item => item)
      if (arr.some(item => item.length !== arr[0].length)) { // 横向是否平整
        return false
      }
      // /纵向是否平整
      let colArr = new Array(arr[0].length).fill(0)
      for (let i = 0; i < arr[0].length; i++) {
        for (let j = 0; j < arr.length; j++) {
          if (arr[j][i]) {
            colArr[i] += 1
          }
        }
      }
      colArr =	colArr.filter(item => item)
      return !colArr.some(item => item !== colArr[0])
    },

    isAllowSplit() { // 是否允许拆分单元格
      if (this.selectCells.length > 1) {
        return false
      }
      // 选中的单元格或者右击的单元格 rowspan或者colspan ！=1
      const info = this.cellInfoParse(this.getCurrSingleCell())
      return info.rowNum > 1 || info.colNum > 1
    },
    // 是否允许设置为单选
    isAllowSetOtherType() {
      if (this.selectCells.length === 0) {
        const info = this.cellInfoParse(this.rightDownCell.dataset.selectFlag)
        return !(info.tag === 'th' || info.rowNum !== 1 || info.colNum !== 1)
      }
      return !this.selectCells.some(item => {
        const info = this.cellInfoParse(item)
        // console.log( info.rowIndex+'' , this.selectCells[0].split('-')[1])
        return (info.tag === 'th' || info.rowIndex + '' !== this.selectCells[0].split('-')[1] ||
        info.rowNum !== 1 || info.colNum !== 1)
      })
    },
    // 获取待操作的单元格
    getActionFlags() {
      return this.selectCells.length === 0
        ? [this.rightDownCell.dataset.selectFlag] : this.selectCells
    },
    // 只能合并文本类型的单元
    isSelectAllThemText() { // 是否选中的都是文本
      return	!this.getActionFlags().some(item => {
        const info = this.cellInfoParse(item)
        const data = 	info.tag === 'th' ? this.renderTHeadData : this.renderTBodyData
        return data[info.rowIndex][info.colIndex].cellType !== 'text'
      })
    },
    // 是否允许设为结果列
    isAllowSetResultCell() {
      if (this.selectCells.length > 1) {
        return false
      }
      const info = 	this.cellInfoParse(this.getCurrSingleCell())
      return info.tag !== 'th'
    },
    /**
		 * 是否允许删除行
		 * @param {Object} event
		 */
    isAllowRemoveRow(event) {
      const cell = getCell(event.toElement || event.explicitOriginalTarget)
      // 得到当前选中单元格的样式配置
      const cellInfoParse = this.cellInfoParse(cell.dataset.selectFlag)

      // 简易模式默认的一行表头不允许被删除
      if (cellInfoParse.tag === 'th' && cellInfoParse.rowIndex + 1 === this.renderTHeadData.length) return false

      // 选中数据都在一行 则可进行删除
      if (this.selectCells.length < 2) {
        return true
      }
      const fristInfo = this.cellInfoParse(this.selectCells[0])
      return 	!this.selectCells.some(item => {
        const info = this.cellInfoParse(item)
        return 	fristInfo.rowIndex !== info.rowIndex
      })
    },
    isAllowRemoveCol() { // 是否允许删除列
    // 选中数据都在一行 则可进行删除
      if (this.selectCells.length < 2) {
        return true
      }
      const fristInfo = this.cellInfoParse(this.selectCells[0])
      return 	!this.selectCells.some(item => {
        const info = this.cellInfoParse(item)
        return 	fristInfo.colIndex !== info.colIndex
      })
    },
    isSetEdit() { // 是否允许设置为可编辑或者不可编辑
    // console.log(this.cellInfoParse(this.rightDownCell.dataset.selectFlag))
      if (this.selectCells.length === 0) {
        const info = this.cellInfoParse(this.rightDownCell.dataset.selectFlag)
        if (info.tag === 'th') {
          return 	this.renderTHeadData[info.rowIndex][info.colIndex].cellType === 'text'
        }
        return 	this.renderTBodyData[info.rowIndex][info.colIndex].cellType === 'text'
      } else {
        for (let i = 0; i < this.selectCells.length; i++) {
          const info = this.cellInfoParse(this.rightDownCell.dataset.selectFlag)
          let celltype = ''
          if (info.tag === 'th') {
            celltype = 	this.renderTHeadData[info.rowIndex][info.colIndex].cellType
          } else {
            celltype = 	this.renderTBodyData[info.rowIndex][info.colIndex].cellType
          }
          if (celltype !== 'text') {
            return false
          }
        }
      }
      return true
    },
    getMenu(event) { // 获取菜单
      this.allowMerging = this.isAllowMerge()
      // 拆分单元格 选中的是一个 或者 没有选中 且右击了单元格 同时 rouspan、colspan ！=1
      //  &&this.isSelectAllThemText()
      const sallowEdit = this.isSetEdit()
      this.menuList = [
        { label: '合并单元格', enable: this.selectCells.length > 1 && this.allowMerging }, // 0
        { label: '拆分单元格', enable: this.isAllowSplit() }, // 1
        { label: '设为结果列', hide: this.tableModel === 0, enable: this.isAllowSetResultCell() }, // 2 tableModel
        { label: '插入行', enable: true }, // 3
        { label: '插入列', enable: true }, // 4
        { label: '删除行', hide: false, enable: this.isAllowRemoveRow(event) },
        { label: '删除列', hide: false, enable: this.isAllowRemoveCol() },
        { label: '设为可编辑单元', hide: true, enable: sallowEdit },
        { label: '设为不可编辑单元', hide: true, enable: sallowEdit },
        { label: '文本对齐方式', hide: true }, // 9
        { label: '清空内容', enable: true }
      ] // 6
      this.$nextTick(() => {
      // 是否加入合并单元格功能
        this.$refs[this.tableId + 'menu'].open(event, (index, val) => {
          switch (index) {
            case 0 : this.mergingCell(); this.selectCells = []; break 		// 合并
            case 1 : this.cellSpilt();	 this.selectCells = []; break 		// 拆分 取消单元格选中
            case 2 : this.setResultCell(); break 													// 设置结果列
            case 3 : this.inserRow(val);	this.selectCells = []; break 			// 插入行
            case 4 : this.insertCol(val); this.selectCells = []; break 			// 插入列
            case 5 : this.removeRow(); this.selectCells = []; break
            case 6 : this.removeCol();	this.selectCells = []; break
            case 7 : this.setEditCell(); break
            case 8 : this.setNoEditCell(); break
            case 9 : this.setTextAligin(val); break
            case 10 : this.clearContent(); break
          }
        })
      })
    },
    /**
		 * 清空内容
		 */
    clearContent() {
      /**
			 * 分两种:
			 * 	1.直接右键,清除当前右键选中单元格的值
			 *  2.多选后右键,清除当前多选的所有单元格的值
			 */
      if (this.selectCells.length) {
        this.selectCells.forEach(item => {
          const info = this.cellInfoParse(item)
          const data = info.tag === 'th' ? this.renderTHeadData : this.renderTBodyData
          data[info.rowIndex][info.colIndex].val = ''
        })
      }
      else {
        const info = this.cellInfoParse(this.getCurrSingleCell())
        const data = info.tag === 'th' ? this.renderTHeadData : this.renderTBodyData
        data[info.rowIndex][info.colIndex].val = ''
      }
    },
    setTextAligin(val) {
      if (this.selectCells.length === 0) {
        const info = this.cellInfoParse(this.rightDownCell.dataset.selectFlag)
        if (info.tag === 'th') {
          this.renderTHeadData[info.rowIndex][info.colIndex].textAlign = val
        } else {
          this.renderTBodyData[info.rowIndex][info.colIndex].textAlign = val
        }
      } else {
        this.selectCells.forEach(cell => {
          const info = this.cellInfoParse(cell)
          if (info.tag === 'th') {
            this.renderTHeadData[info.rowIndex][info.colIndex].textAlign = val
          } else {
            this.renderTBodyData[info.rowIndex][info.colIndex].textAlign = val
          }
        })
      }
      this.$forceUpdate()
    },
    // isEditCell
    setEditCell() {
      if (this.selectCells.length === 0) {
        const info = this.cellInfoParse(this.rightDownCell.dataset.selectFlag)
        if (info.tag === 'th') {
          this.renderTHeadData[info.rowIndex][info.colIndex].isEditCell = true
        } else {
          this.renderTBodyData[info.rowIndex][info.colIndex].isEditCell = true
        }
      } else {
        this.selectCells.forEach(cell => {
          const info = this.cellInfoParse(cell)
          if (info.tag === 'th') {
            this.renderTHeadData[info.rowIndex][info.colIndex].isEditCell = true
          } else {
            this.renderTBodyData[info.rowIndex][info.colIndex].isEditCell = true
          }
        })
      }
    },
    setNoEditCell() {
      if (this.selectCells.length === 0) {
        const info = this.cellInfoParse(this.rightDownCell.dataset.selectFlag)
        if (info.tag === 'th') {
          this.renderTHeadData[info.rowIndex][info.colIndex].isEditCell = false
        } else {
          this.renderTBodyData[info.rowIndex][info.colIndex].isEditCell = false
        }
      } else {
        this.selectCells.forEach(cell => {
          const info = this.cellInfoParse(cell)
          if (info.tag === 'th') {
            this.renderTHeadData[info.rowIndex][info.colIndex].isEditCell = false
          } else {
            this.renderTBodyData[info.rowIndex][info.colIndex].isEditCell = false
          }
        })
      }
    },
    removeRow() { // 删除行
      const info = this.cellInfoParse(this.getCurrSingleCell())
      // 删除当前行需要考虑合并 rowspan
      const data = this.getOperateData(info.tag).slice(0)
      for (let i = 0; i < info.rowIndex; i++) {
        for (let j = 0; j < data[i].length; j++) {
          if (data[i][j].rowspan + i > info.rowIndex) { // 当有合并行 且不是删除起始行 则需要rowspan减一
            data[i][j].rowspan--
          }
        }
      }
      if (data.length === info.rowIndex + 1) {
      // 直接删除
        data.splice(info.rowIndex, 1)
        if (info.tag === 'th') {
          this.renderTHeadData = []
          this.$nextTick(() => {
            this.renderTHeadData = data
          })
        } else {
          this.renderTBodyData = []
          this.$nextTick(() => {
            this.renderTBodyData = data
          })
        }
        this.rowCelChange()
        return
      }
      for (let i = 0; i < data[info.rowIndex].length; i++) {
      // 判断删除的这一行 是否为合并首行 是的话 将由下一行继承部分属性
        if (data[info.rowIndex][i].rowspan > 1) {
          data[info.rowIndex + 1][i].rowspan = data[info.rowIndex][i].rowspan - 1
          data[info.rowIndex + 1][i].isRemove = false
          data[info.rowIndex + 1][i].colspan = data[info.rowIndex][i].colspan
        }
      }
      data.splice(info.rowIndex, 1)
      if (info.tag === 'th') {
        this.renderTHeadData = []
        this.$nextTick(() => {
          this.renderTHeadData = data
        })
      } else {
        this.renderTBodyData = []
        this.$nextTick(() => {
          this.renderTBodyData = data
        })
      }
      this.rowCelChange()
    },
    removeCol() { // 删除列
      const info = this.cellInfoParse(this.getCurrSingleCell())
      // 删除列 //删除当前行需要考虑合并 rowspan colspan
      const arr = [this.renderTHeadData.slice(0), this.renderTBodyData.slice(0)]
      arr.forEach(data => {
        for (let i = 0; i < data.length; i++) {
          for (let j = info.colIndex; j >= 0; j--) {
            if (data[i][j].colspan + j > info.colIndex && j < info.colIndex) { // 当有合并行 且不是删除起始行 则需要rowspan减一
              data[i][j].colspan--
            }
            if (info.colIndex + 1 === data[i].length) { // 直接删除
              data[i].splice(j, 1)
            } else if (info.colIndex === j) { // 否则判断是否是需要进行操作的行
            // 如果删除的是合并首列 则需要进行属性继承
              if (data[i][j].colspan > 1) {
                data[i][j + 1].colspan = data[i][j].colspan - 1
                data[i][j + 1].isRemove = false
                data[i][j + 1].rowspan = data[i][j].rowspan
              }
              data[i].splice(j, 1)
            }
          }
        }
      })
      this.renderTHeadData = []
      this.renderTBodyData = []
      this.$nextTick(() => {
        this.renderTHeadData = arr[0]
        this.renderTBodyData = arr[1]
      })
      this.rowCelChange()
    },
    setResultCell() { // 设置结果列
      // this.$refs[this.tableId + 'setTypeTip'].close()
      // 只允许有一个结果列
      for (let i = 0; i < this.renderTBodyData.length; i++) {
        for (let j = 0; j < this.renderTBodyData[i].length; j++) {
          if (this.renderTBodyData[i][j].cellType === 'result') {
            this.renderTBodyData[i][j].cellType = 'text'
          }
        }
      }
      const info = this.cellInfoParse(this.getCurrSingleCell())
      const cell = this.renderTBodyData[info.rowIndex][info.colIndex]
      cell.cellType = 'result'
      cell.val = ''
      cell.label = ''
    },
    cellInfoParse(currSelect) { // 单元格信息解析
      const info = currSelect.split('-')
      const tag = info[0]
      const rowIndex = parseInt(info[1])
      const colIndex = parseInt(info[2])
      const rowNum = parseInt(info[3])
      const colNum = parseInt(info[4])
      return { tag, rowIndex, colIndex, rowNum, colNum }
    },
    getCurrSingleCell() { // 获取当前需要操作的单个单元格 selectFlag
      return this.selectCells.length
        ? this.selectCells[0] : this.rightDownCell.dataset.selectFlag
    },
    /**
		 * 插入列
		 */
    insertCol(direction) {
      const info = this.cellInfoParse(this.getCurrSingleCell())
      const itemArr = [this.renderTHeadData,	this.renderTBodyData]
      let isHide = 0
      itemArr.forEach((arr, rowIndex) => { // 表头 /表体
        arr.forEach((item) => { // 行
          // 对行进行遍历 往指定索引插入数据
          for (let i = 0; i < info.colIndex; i++) { // 计算插入列前是否存在合并行
            if (!item[i].isRemove && item[i].colspan !== 1 && item[i].colspan + i > info.colIndex) {
              item[i].colspan += 1
              isHide = item[i].rowspan
            }
          }
          // 给出默认值
          const cell = { ... defaultCell }

          // 判断是否为表头
          if (this.renderTHeadData.length > rowIndex) {
            // 设置为表头
            cell.isWeight = cell.isShow = true
            cell['cellFill'] = '#F9FAFB'
          }
          else {
            // 设置为表体
            cell['cellFill'] = '#FFFFFF'
          }
          cell.isRemove = isHide > 0
          isHide-- // 处理多行合并时的问题
          item.splice(info.colIndex + (direction === 'left' ? 0 : 1), 0, cell)
        })
      })
      this.rowCelChange()
    },
    /**
		 * 插入行
		 */
    inserRow(direction) {
      let fiexdHeaderDown = false
      // 固定的表头&&向下插入行=向下插入一行表体
      let info = this.cellInfoParse(this.getCurrSingleCell())
      if (info.tag === 'th' && direction === 'down' && info.rowIndex + 1 === this.renderTHeadData.length) {
        fiexdHeaderDown = true
        info = this.cellInfoParse('td-0-0-1-1')
      }

      const data = this.getOperateData(info.tag)
      const copyRow = JSON.parse(JSON.stringify(data[info.rowIndex])).map(item => {
        const cell = { ... defaultCell } // 给出默认值
        // 保留部分属性
        cell.colspan = item.colspan || 1
        cell.isRemove = item.isRemove
        cell.isWeight = cell.isItalic = cell.underline = cell.isShow = info.tag === 'th'
        return cell
      })
      // 加入数据
      // 向上追溯 有无rospan>=该行的 有的话 需要为其rowspan+1
      for (let i = 0; i < info.rowIndex; i++) {
        data[i].forEach((item, index) => {
          // 如果这一个单元格被隐藏
          // 如果这个单元格合并过
          if (!item.isRemove && item.rowspan !== 1 &&
              item.rowspan + i > info.rowIndex) {
            item.rowspan += 1
          }
        })
      }

      // 表体填充背景色
      if (info.tag === 'td' || fiexdHeaderDown) {
        copyRow.forEach(item => {
          item['cellFill'] = '#FFFFFF'
        })
      }

      // 如果是在固定的表头进行向下插入则插入一行表体
      data.splice(info.rowIndex + (direction === 'up' || fiexdHeaderDown ? 0 : 1), 0, copyRow)

      this.rowCelChange()
    },
    getOperateData(tag) {
      return tag === 'th' ? this.renderTHeadData : this.renderTBodyData
    },
    // 单元格拆分
    cellSpilt() {
      const info = this.cellInfoParse(this.getCurrSingleCell())
      // 得到要进行操作的数据
      const data = this.getOperateData(info.tag)
      for (let i = info.rowIndex; i < info.rowIndex + info.rowNum; i++) {
        for (let j = info.colIndex; j < info.colIndex + info.colNum; j++) {
          data[i][j].rowspan = 1
          data[i][j].colspan = 1
          data[i][j].isRemove = false
          data[i][j].isEditCell = false
        }
      }
    },
    mergingCell() { // 单元格合并
    // 标签名-行-列-rowspan-colspan
      const info = this.selectCells[0].split('-')
      const selectData = []
      // 需要操作多少行
      this.selectCells.forEach((cell, index) => {
        const row = parseInt(cell.split('-')[1])
        const col = parseInt(cell.split('-')[2])
        if (!selectData[row]) {
          selectData[row] = []
        }
        selectData[row][col] = {
          rowspan: parseInt(cell.split('-')[3]),
          colspan: parseInt(cell.split('-')[4])
        }
      })
      // 选择进行操作的数据
      const data = this.getOperateData(info[0])
      // 设置rowspan 与colspan
      const startRow = selectData.findIndex(item => item)
      let currRowspan = 0
      for (let i = startRow; i < selectData.length;) {
        if (selectData[i] && selectData[i][parseInt(info[2])]) {
          currRowspan += selectData[i][parseInt(info[2])].rowspan
          i += selectData[i][parseInt(info[2])].rowspan
        } else {
          currRowspan += 1
          i++
        }
      }
      data[parseInt(info[1])][parseInt(info[2])].rowspan = currRowspan
      const colspanArr = selectData[parseInt(info[1])].map(item => item.colspan).filter(item => item)
      const currColspan = colspanArr.length > 1 ? sum(colspanArr) : colspanArr[0]
      data[parseInt(info[1])][parseInt(info[2])].colspan = currColspan
      data[parseInt(info[1])][parseInt(info[2])].cellType = 'text' // 合并后 设为文本
      let isFrist = true
      selectData.forEach((item, index) => {
        if (item) { // 因为是直接用下标插入的 所以会有empty存在
        // 获取删除起始下标 与删除个数
          let startIndex = item.findIndex(d => d)
          let removeLength = 0
          for (let i = startIndex; i < item.length; i++) {
            removeLength += item[i] ? item[i].colspan : 0
          }
          if (isFrist) { // 第一个数据应该进行保留
            startIndex++
            removeLength--
            isFrist = false
            if (removeLength === 0) {
              return
            }
          }
          for (let i = startIndex; i < startIndex + removeLength; i++) {
            data[index][i].isRemove = true
            // data[index][i].val = ''
          }
        }
      })
    },
    // --------------------常规事件方法
    changeRadio(row, col) {
      if (row !== undefined && col !== undefined) {
        this.renderTBodyData[row].forEach((item, index) => {
          item.otherSelect = (col === index ? true : null)
        })
      }
    }
  }
}
</script>

<style lang="scss" scoped>
.select{
  background:#FAF0DE !important;
}
.isedit{
  background-color:#f2faf3 !important;
}
.dynamic-table-wapper{
  // padding:20px;
  // min-height: 200px;
  border-radius: 5px;
  overflow: hidden;
  // border:1px solid #dfe6ec;
  table-layout:fixed;
  .isPreview{
    user-select: auto !important;
  }
  .noPreview{
    user-select: none !important;
  }
  .dynamic-table{
    width:100%;
    border-collapse: collapse;
    &:first-child tr{
      th{
        border-top:none !important;
      }
    }
    tr{
      &:first-child th{
        border-top:none !important;
        border-left:none !important;
      }
      th:first-child,td:first-child{
        border-left:none !important;
      }
      th:last-child,td:last-child{
        border-right:none !important;
      }
      &:last-child td{
        border-bottom:none !important;
      }
    }
    th{
      // background-color: #F9FAFB;
      font-weight: 300;
    }
    td{
      font-size:14px;
      color:#222222;
      // background-color: #ffffff;
    }
    td,th{
      word-wrap:break-word;
      border-spacing: 0;
      // border:1px solid #dfe6ec;
      box-sizing:border-box;
      padding:5px;
      overflow-x: auto;
    }
  }
}
.brder-right-none{
    border-right:none !important;
}
.brder-bottom-none{
    border-bottom:none !important;
}
.table-title{
  text-align:center;
  padding:10px 0;
  font-size:16px;
  font-weight:600;
}
</style>
